﻿using System;
using System.Collections.Generic;
using System.Text;
using btom = Microsoft.BizTalk.ExplorerOM;
using HenIT.Utilities;
using System.IO;
using HenIT.BizTalk;

//Important note. 
//This app must be compiled for 32bit execution only since BTS Explorer OM does not support 64bit 
//Yes I know, this sucks

namespace HenIT.BizTalk
{
    class Program
    {
        static void Main(string[] args)
        {
            if (CommandLineUtils.IsCommand(args, "/?", "-?", "/h", "-h"))
                ShowHelp();
            else
            {
                string trackingOptionsFilePath = CommandLineUtils.GetDefault(args, System.IO.Path.Combine(System.Environment.CurrentDirectory, "TrackingOptions.xml"));
                string sqlServer = CommandLineUtils.GetCommand(args, BizTalkUtils.GetCurrentBizTalkSqlServer(), "-srv:", "/srv:");
                string bizTalkMgmtDb = CommandLineUtils.GetCommand(args, BizTalkUtils.GetCurrentBizTalkMgmtDb(), "-db:", "/db:");
                string appName = CommandLineUtils.GetCommand(args, "", "/a:", "-a:");
                string receivePortName = CommandLineUtils.GetCommand(args, "", "/r:", "-r:");
                string sendPortName = CommandLineUtils.GetCommand(args, "", "/s:", "-s:");
                string orchestrationName = CommandLineUtils.GetCommand(args, "", "/o:", "-o:");
                string pipelineName = CommandLineUtils.GetCommand(args, "", "/p:", "-p:");

                FileStream outstream = File.Create(trackingOptionsFilePath);
                using (System.Xml.XmlTextWriter wrt = new System.Xml.XmlTextWriter(outstream, Encoding.UTF8))
                {
                    wrt.Formatting = System.Xml.Formatting.Indented;
                    wrt.Indentation = 5;
                    wrt.IndentChar = ' ';
                    wrt.WriteStartDocument();
                    wrt.WriteStartElement("trackingOptions");

                    using (btom.BtsCatalogExplorer catalog = new btom.BtsCatalogExplorer())
                    {
                        catalog.ConnectionString = "SERVER=" + sqlServer + ";DATABASE=" + bizTalkMgmtDb + ";Integrated Security=SSPI";

                        foreach (btom.Application app in catalog.Applications)
                        {
                            if (appName.Length == 0 || appName == app.Name)
                            {
                                wrt.WriteStartElement("application");
                                wrt.WriteAttributeString("name", app.Name);

                                if (!app.IsSystem)
                                {
                                    //Receive ports
                                    wrt.WriteStartElement("receivePorts");
                                    foreach (btom.ReceivePort rp in app.ReceivePorts)
                                    {
                                        if (receivePortName.Length == 0 || receivePortName == rp.Name)
                                        {
                                            wrt.WriteStartElement("receivePort");
                                            wrt.WriteAttributeString("name", rp.Name);
                                            wrt.WriteStartElement("tracking");

                                            if ((int)rp.Tracking == 0)
                                            {
                                                wrt.WriteStartElement("add");
                                                wrt.WriteEndElement();
                                            }
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.BeforeReceivePipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.AfterReceivePipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.BeforeSendPipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.AfterSendPipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.TrackPropertiesBeforeReceivePipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.TrackPropertiesAfterReceivePipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.TrackPropertiesBeforeSendPipeline);
                                            WriteTrackingType(wrt, rp.Tracking, btom.TrackingTypes.TrackPropertiesAfterSendPipeline);

                                            wrt.WriteStartElement("remove");
                                            wrt.WriteEndElement(); //remove - none
                                            wrt.WriteEndElement(); //tracking
                                            wrt.WriteEndElement(); //receivePort
                                        }
                                    }
                                    wrt.WriteEndElement();

                                    //Send ports
                                    wrt.WriteStartElement("sendPorts");
                                    foreach (btom.SendPort sp in app.SendPorts)
                                    {
                                        if (sendPortName.Length == 0 || sendPortName == sp.Name)
                                        {
                                            wrt.WriteStartElement("sendPort");
                                            wrt.WriteAttributeString("name", sp.Name);
                                            wrt.WriteStartElement("tracking");

                                            if ((int)sp.Tracking == 0)
                                            {
                                                wrt.WriteStartElement("add");
                                                wrt.WriteEndElement();
                                            }
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.BeforeReceivePipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.AfterReceivePipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.BeforeSendPipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.AfterSendPipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.TrackPropertiesBeforeReceivePipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.TrackPropertiesAfterReceivePipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.TrackPropertiesBeforeSendPipeline);
                                            WriteTrackingType(wrt, sp.Tracking, btom.TrackingTypes.TrackPropertiesAfterSendPipeline);

                                            wrt.WriteStartElement("remove");
                                            wrt.WriteEndElement(); //remove - none
                                            wrt.WriteEndElement(); //tracking

                                            wrt.WriteEndElement();//sendPort
                                        }
                                    }
                                    wrt.WriteEndElement();

                                    //Orchestrations
                                    wrt.WriteStartElement("orchestrations");
                                    foreach (btom.BtsOrchestration o in app.Orchestrations)
                                    {
                                        if (orchestrationName.Length == 0 || orchestrationName == o.FullName)
                                        {
                                            wrt.WriteStartElement("orchestration");
                                            wrt.WriteAttributeString("name", o.FullName);
                                            wrt.WriteStartElement("tracking");

                                            if ((int)o.Tracking == 0)
                                            {
                                                wrt.WriteStartElement("add");
                                                wrt.WriteEndElement();
                                            }
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.ServiceStartEnd);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.MessageSendReceive);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.InboundMessageBody);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.OutboundMessageBody);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.OrchestrationEvents);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.TrackPropertiesForIncomingMessages);
                                            WriteTrackingType(wrt, o.Tracking, btom.OrchestrationTrackingTypes.TrackPropertiesForOutgoingMessages);

                                            wrt.WriteStartElement("remove");
                                            wrt.WriteEndElement(); //remove - none
                                            wrt.WriteEndElement(); //tracking

                                            wrt.WriteEndElement(); //orchestration
                                        }
                                    }
                                    wrt.WriteEndElement();
                                }

                                //Pipelines
                                wrt.WriteStartElement("pipelines");
                                foreach (btom.Pipeline p in app.Pipelines)
                                {
                                    if (pipelineName.Length == 0 || pipelineName == p.FullName)
                                    {
                                        wrt.WriteStartElement("pipeline");
                                        wrt.WriteAttributeString("name", p.FullName);
                                        wrt.WriteStartElement("tracking");

                                        if (p.Tracking == Microsoft.BizTalk.ExplorerOM.PipelineTrackingTypes.None || p.Tracking == Microsoft.BizTalk.ExplorerOM.PipelineTrackingTypes.PipelineEvents)
                                        {
                                            wrt.WriteStartElement("add");
                                            wrt.WriteEndElement();
                                        }

                                        WriteTrackingType(wrt, p.Tracking, btom.PipelineTrackingTypes.ServiceStartEnd);
                                        WriteTrackingType(wrt, p.Tracking, btom.PipelineTrackingTypes.MessageSendReceive);
                                        WriteTrackingType(wrt, p.Tracking, btom.PipelineTrackingTypes.InboundMessageBody);
                                        WriteTrackingType(wrt, p.Tracking, btom.PipelineTrackingTypes.OutboundMessageBody);

                                        wrt.WriteStartElement("remove");
                                        wrt.WriteEndElement(); //remove - none
                                        wrt.WriteEndElement(); //tracking

                                        wrt.WriteEndElement(); //pipeline
                                    }
                                }
                                wrt.WriteEndElement(); 
                                wrt.WriteEndElement(); //application
                            }
                        }
                    }
                    wrt.WriteEndElement();
                    wrt.WriteEndDocument();
                    wrt.Flush();
                }
                outstream.Close();
                Console.WriteLine("Done");
            }
        }

        #region WriteTrackingType
        private static void WriteTrackingType(System.Xml.XmlTextWriter wrt, btom.TrackingTypes tracking, btom.TrackingTypes compareTo)
        {
            if (IsTrackingTypes(tracking, compareTo))
            {
                wrt.WriteStartElement("add");
                wrt.WriteAttributeString("key", compareTo.ToString());
                wrt.WriteEndElement();
            }
        }
        private static void WriteTrackingType(System.Xml.XmlTextWriter wrt, btom.OrchestrationTrackingTypes tracking, btom.OrchestrationTrackingTypes compareTo)
        {
            if (IsTrackingTypes(tracking, compareTo))
            {
                wrt.WriteStartElement("add");
                wrt.WriteAttributeString("key", compareTo.ToString());
                wrt.WriteEndElement();
            }
        }
        private static void WriteTrackingType(System.Xml.XmlTextWriter wrt, btom.PipelineTrackingTypes tracking, btom.PipelineTrackingTypes compareTo)
        {
            if (IsTrackingTypes(tracking, compareTo))
            {
                wrt.WriteStartElement("add");
                wrt.WriteAttributeString("key", compareTo.ToString());
                wrt.WriteEndElement();
            }
        } 
        #endregion

        #region IsTrackingTypes
        private static bool IsTrackingTypes(btom.TrackingTypes tracking, btom.TrackingTypes compareTo)
        {
            return ((tracking & compareTo) == compareTo);
        }
        private static bool IsTrackingTypes(btom.OrchestrationTrackingTypes tracking, btom.OrchestrationTrackingTypes compareTo)
        {
            return ((tracking & compareTo) == compareTo);
        }
        private static bool IsTrackingTypes(btom.PipelineTrackingTypes tracking, btom.PipelineTrackingTypes compareTo)
        {
            return ((tracking & compareTo) == compareTo);
        } 
        #endregion

        static void ShowHelp()
        {
            Console.WriteLine("Usage: BTSGetTrackingOptions.exe <TrackingOptionsFile> [-srv:server] [-db:MgmtDb] [-a:app] [-r:receivePort] [/s:sendPort] [-o:orchestration] [-p:pipeline]");
            Console.WriteLine(" where");
            Console.WriteLine("   TrackingOptionsFile : xml file to export tracking options to");
            Console.WriteLine("   srv : Sql server");
            Console.WriteLine("   db  : Management database e.g. BizTalkMgmtDb");
            Console.WriteLine("   a   : Application name");
            Console.WriteLine("   r   : Receive port name");
            Console.WriteLine("   s   : Send port name");
            Console.WriteLine("   o   : Orchestration name");
            Console.WriteLine("   p   : Pipeline name");
        }
    }
}
